package studio.raptor.ddal.core.engine;

import java.net.InetAddress;
import java.sql.SQLException;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import studio.raptor.ddal.core.connection.BackendConnection;
import studio.raptor.ddal.core.connection.jdbc.JdbcBackendConnection;
import studio.raptor.ddal.core.executor.ExecutionUnit;
import studio.raptor.ddal.core.log.LogClientUtil;
import studio.raptor.ddal.core.log.bo.SqlProcessLogData;

/**
 * 执行日志
 *
 * @author Charley
 * @since 1.0
 */
public class SqlProcessLog {

  private static final Logger LOGGER = LoggerFactory.getLogger(SqlProcessLog.class);

  private StatementContext statementContext;

  //跟踪ID
  private final String traceId = UUID.randomUUID().toString();
  private Date startTime;
  private Date endTime;
  private String hostIp;
  private String errorMsg;


  public SqlProcessLog(StatementContext statementContext) {
    try{
      this.statementContext = statementContext;
      this.startTime = new Date();
      this.hostIp = InetAddress.getLocalHost().toString();
    }catch (Exception ignore){
    }
  }

  private SqlProcessLogData fillOutPut(SqlProcessLogData sqlProcessLogData){
    this.endTime = new Date();
    sqlProcessLogData.setTraceId( this.traceId );
    sqlProcessLogData.setHostIp( this.hostIp );
    sqlProcessLogData.setStartTime( this.startTime );
    sqlProcessLogData.setEndTime( this.endTime );
    sqlProcessLogData.setProcessTime( endTime.getTime() - startTime.getTime());
    sqlProcessLogData.setSqlType( statementContext.getSqlStatementType().getType());
    sqlProcessLogData.setShards( statementContext.getRouteResult().getDbShard());
    if(statementContext.isAddBatch()||statementContext.isExecuteBatch()){
      try {
        sqlProcessLogData.setFinalSqlList(statementContext.getBatchSqlList() );
        Collection<BackendConnection> connections=statementContext.getBackendConnectionMap().values();
        JdbcBackendConnection jdbconnection;
        for (BackendConnection connection:connections){
          jdbconnection=(JdbcBackendConnection)connection;
          sqlProcessLogData.getDataSources().add(jdbconnection.getConnection().getMetaData().getURL());
          sqlProcessLogData.getDbUsers().add(jdbconnection.getConnection().getMetaData().getUserName());
        }
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }else{
      try {
        List<ExecutionUnit> executionUnits=statementContext.getCurrentExecutionGroup().getExecutionUnits();
        JdbcBackendConnection jdbconnection;
        for (ExecutionUnit exeUnit:executionUnits){
          sqlProcessLogData.getFinalSqlList().add( exeUnit.getFinalSql() );
          jdbconnection=(JdbcBackendConnection)exeUnit.getConnection();
          sqlProcessLogData.getDataSources().add(jdbconnection.getConnection().getMetaData().getURL());
          sqlProcessLogData.getDbUsers().add(jdbconnection.getConnection().getMetaData().getUserName());
        }
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    sqlProcessLogData.setTables( statementContext.getParseResult().getTableNames());
    sqlProcessLogData.setSql( statementContext.getOriginSql());
    sqlProcessLogData.setParameters( statementContext.getSqlParameters());
    sqlProcessLogData.setPlan(statementContext.getPlanInstance().toString());
    if(null!= this.errorMsg){
      sqlProcessLogData.setSucess( false );
      sqlProcessLogData.setErrorMsg( this.errorMsg.trim());
    }
    sqlProcessLogData.setAcceptTime( new Date() );
    return sqlProcessLogData;
  }

  public void print(){
    SqlProcessLogData sqlProcessLogData=LogClientUtil.getSqlProcessLogData();
    if(null != sqlProcessLogData){
      fillOutPut(sqlProcessLogData);
      print0(sqlProcessLogData);
    }
  }

  private void print0(SqlProcessLogData sqlProcessLogData){
    LOGGER.debug(sqlProcessLogData.toString());
    LogClientUtil.process(sqlProcessLogData);
  }

  public String getErrorMsg() {
    return errorMsg;
  }

  public void setErrorMsg(String errorMsg) {
    this.errorMsg = errorMsg;
  }
}
